#include "effecteventhandler.h"
#include "effecteventmanager.h"

namespace VrDataCore
{
	EffectEventHandler::EffectEventHandler(EffectEventManager* eem):_eem(eem),_handlerAllEvent(false)
	{}

	bool EffectEventHandler::handle(
		const osgGA::GUIEventAdapter& gea,
		osgGA::GUIActionAdapter&      gaa,
		osg::Object*                  obj,
		osg::NodeVisitor*             nv) 
	{
		if(_handlerAllEvent)
		{
			AllAction haa = _getAllAction();
			if(haa)
				return (this->*haa)((osgGA::GUIEventAdapter*)&gea,&gaa);
		}
		osgGA::GUIEventAdapter::EventType ev = gea.getEventType();
		FrameAction fa = _isFrameEvent(ev);
		if(fa)
		{
			return (this->*fa)((osgGA::GUIEventAdapter*)&gea,&gaa);
		}
		MouseAction                       ma = _isMouseEvent(ev);
		if(ma) 
		{
			// If we're scrolling, we need to inform the WindowManager of that.
			//_wm->setScrollingMotion(gea.getScrollingMotion());
			// osgWidget assumes origin is bottom left of window so make sure mouse coordinate are increaseing y upwards and are scaled to window size.
			float x = (gea.getX()-gea.getXmin())/(gea.getXmax()-gea.getXmin())*static_cast<float>(gea.getWindowWidth());
			float y = (gea.getY()-gea.getYmin())/(gea.getYmax()-gea.getYmin())*static_cast<float>(gea.getWindowHeight());
			if (gea.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS) y = static_cast<float>(gea.getWindowHeight())-y;
			//OSG_NOTICE<<"EffectEventHandler(x="<<x<<", y="<<y<<")"<<std::endl;
			return (this->*ma)(x, y, gea.getButton());
		}
		KeyAction ka = _isKeyEvent(ev);
		if(ka) 
		{
			float x = (gea.getX()-gea.getXmin())/(gea.getXmax()-gea.getXmin())*static_cast<float>(gea.getWindowWidth());
			float y = (gea.getY()-gea.getYmin())/(gea.getYmax()-gea.getYmin())*static_cast<float>(gea.getWindowHeight());
			if (gea.getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS) y = static_cast<float>(gea.getWindowHeight())-y;
			return (this->*ka)(x, y, gea.getKey());
		}
		return false;
	}

	bool EffectEventHandler::_handleMousePush(float x, float y, int button) {
		if(button == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) 
			return _doMouseEvent(x,y,&EffectEventManager::mousePushedLeft);
		else if(button == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) 
			return _doMouseEvent(x,y,&EffectEventManager::mousePushedRight);
		else if(button == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) 
			return _doMouseEvent(x,y,&EffectEventManager::mousePushedMiddle);
		else 
			return false;
	}

	bool EffectEventHandler::_handleMouseRelease(float x, float y, int button) {
		if(button == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON) 
			return _doMouseEvent(x,y,&EffectEventManager::mouseReleasedLeft);
		else if(button == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON) 
			return _doMouseEvent(x,y,&EffectEventManager::mouseReleasedRight);
		else if(button == osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON) 
			return _doMouseEvent(x,y,&EffectEventManager::mouseReleasedMiddle);
		else return 
			false;
	}

	bool EffectEventHandler::_handleMouseDoubleClick(float /*x*/, float /*y*/, int /*button*/) 
	{
		return false;
	}

	bool EffectEventHandler::_handleMouseDrag(float x, float y, int /*button*/) 
	{
		return _doMouseEvent(x, y, &EffectEventManager::pointerDrag);
	}

	bool EffectEventHandler::_handleMouseMove(float x, float y, int /*button*/) 
	{
		return _doMouseEvent(x, y, &EffectEventManager::pointerMove);
	}

	bool EffectEventHandler::_handleMouseScroll(float x, float y, int) 
	{
		return _doMouseEvent(x, y, &EffectEventManager::mouseScroll);
	}

	EffectEventHandler::MouseAction EffectEventHandler::_isMouseEvent(
		osgGA::GUIEventAdapter::EventType ev) const 
	{
		if(ev == osgGA::GUIEventAdapter::PUSH) 
			return &EffectEventHandler::_handleMousePush;
		else if(ev == osgGA::GUIEventAdapter::RELEASE)
			return &EffectEventHandler::_handleMouseRelease;
		else if(ev == osgGA::GUIEventAdapter::DOUBLECLICK) 
			return &EffectEventHandler::_handleMouseDoubleClick;
		else if(ev == osgGA::GUIEventAdapter::DRAG) 
			return &EffectEventHandler::_handleMouseDrag;
		else if(ev == osgGA::GUIEventAdapter::MOVE) 
			return &EffectEventHandler::_handleMouseMove;
		else if(ev == osgGA::GUIEventAdapter::SCROLL) 
			return &EffectEventHandler::_handleMouseScroll;
		else return 0;
	}

	bool EffectEventHandler::_doMouseEvent(float x, float y, MouseEvent me) 
	{
		bool handled = (_eem->*me)(x, y);
		// This is called LAST for things like drag, which needs to calculate a mouse difference.
		_eem->setPointerXY(x, y);
		return handled;
	}

	EffectEventHandler::KeyAction EffectEventHandler::_isKeyEvent (osgGA::GUIEventAdapter::EventType ev) const
	{
		if(ev == osgGA::GUIEventAdapter::KEYDOWN) 
			return &EffectEventHandler::_handleKeyDown;
		else if(ev == osgGA::GUIEventAdapter::KEYUP)
			return &EffectEventHandler::_handleKeyUp;
		else return 0;
	}

	bool EffectEventHandler::_handleKeyDown(float x, float y, int key)
	{
		return _doKeyEvent(x, y, key,&EffectEventManager::keyDown);
	}

	bool EffectEventHandler::_handleKeyUp(float x, float y, int key)
	{
		return _doKeyEvent(x, y, key,&EffectEventManager::keyUp);
	}

	bool EffectEventHandler::_doKeyEvent (float x, float y, int key, EffectEventHandler::KeyEvent ke)
	{
		bool handled = (_eem->*ke)(x, y, key);
		return handled;
	}

	EffectEventHandler::FrameAction EffectEventHandler::_isFrameEvent(osgGA::GUIEventAdapter::EventType ev) const
	{
		if(ev == osgGA::GUIEventAdapter::FRAME) 
			return &EffectEventHandler::_handleFrame;
		return 0;
	}

	bool EffectEventHandler::_handleFrame (osg::ref_ptr<osgGA::GUIEventAdapter>ea,osgGA::GUIActionAdapter* aa)
	{
		return _doFrameEvent(ea,aa,&EffectEventManager::frame);
	}

	bool	EffectEventHandler::_doFrameEvent (osg::ref_ptr<osgGA::GUIEventAdapter>ea,osgGA::GUIActionAdapter* aa, EffectEventHandler::FrameEvent fe)
	{
		bool handled = (_eem->*fe)(ea,aa);
		return handled;
	}

	EffectEventHandler::AllAction EffectEventHandler::_getAllAction()
	{
		return &EffectEventHandler::_handleAll;
	}

	bool EffectEventHandler::_handleAll(osg::ref_ptr<osgGA::GUIEventAdapter>ea,osgGA::GUIActionAdapter* aa)
	{
		return _doHandleAll(ea,aa,&EffectEventManager::handle);
	}

	bool EffectEventHandler::_doHandleAll (osg::ref_ptr<osgGA::GUIEventAdapter>ea,osgGA::GUIActionAdapter* aa,AllEvent ha)
	{
		bool handled = (_eem->*ha)(ea,aa);
		return handled;
	}
}